"""
Case Type   : 资源池化
Case Name   : 资源池化场景下，开启事务内写转发&备机支持缓存快照信息，主节点dss异常
Create At   : 2024.5
Owner       : haomeng802
Description :
    1、查看集群状态 cm_ctl query -Cv
    2、开启事务内写转发&备机支持缓存快照信息，重启集群
    3、主节点dss进程退出（kill方式）
        ps ux | grep -v grep | grep dssserver | awk '{print $2}' | xargs kill -9
    4、再次查看dss进程,观察CMS服务是否会自动拉起恢复dss,查看集群状态
    5、恢复集群原始状态
        cm_ctl start,cm_ctl switchover -a
Expect      :
    1、集群状态正常，数据库节点状态正常
    2、参数配置成功，集群重启成功
    3、kill主节点dss进程成功
    4、dss进程不存在,cms进程未拉起恢复dss,集群状态异常
    5、恢复集群成功，集群状态正常
History     :
"""

import os
import time
import unittest

from testcase.utils.ComThread import ComThread
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro

Primary_SH = CommonSH('PrimaryDbUser')


@unittest.skipIf(3 != Primary_SH.get_node_num(), '非1+2环境不执行')
class SharedStorage(unittest.TestCase):

    def setUp(self):
        self.log = Logger()
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.constant = Constant()
        self.com = Common()
        self.usernode = Node('PrimaryDbUser')
        self.remote_excute = 'enable_remote_excute'
        self.bcast_snapshot = 'ss_enable_bcast_snapshot'
        self.remote_excute_default = self.com.show_param(self.remote_excute)
        self.bcast_snapshot_default = self.com.show_param(self.bcast_snapshot)

    def test_shared_storage(self):
        text = '-----step1:查看集群状态; expect:集群状态正常-----'
        self.log.info(text)

        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        self.assertIn('cluster_state   : Normal', status, '执行失败' + text)

        text = '----step2:开启事务内写转发&备机支持缓存快照信息,重启集群; expect:参数设置成功,集群重启成功----'
        self.log.info(text)

        set_param1 = Primary_SH.execute_gsguc('set',
                                              self.constant.GSGUC_SUCCESS_MSG,
                                              f'{self.remote_excute} = on')
        self.log.info(set_param1)
        self.assertTrue(set_param1, 'remote_excute设置失败')

        set_param2 = Primary_SH.execute_gsguc('set',
                                              self.constant.GSGUC_SUCCESS_MSG,
                                              f'{self.bcast_snapshot} = on')
        self.log.info(set_param2)
        self.assertTrue(set_param2, 'bcast_snapshot设置失败')

        stop = Primary_SH.exec_cm_ctl('stop')
        self.log.info(stop)
        start = Primary_SH.exec_cm_ctl('start')
        self.log.info(start)

        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        self.assertIn('cluster_state   : Normal', status, '执行失败' + text)

        text = '-----step3:kill掉主节点dss进程; expect:成功-----'
        self.log.info(text)

        for i in range(7):
            pri_dss_pid1 = self.com.get_pid(self.usernode, 'dssserver')
            self.log.info(pri_dss_pid1)
            self.kill_dss = self.usernode.sh(f'kill -9 {pri_dss_pid1}').result()
            self.log.info(self.kill_dss)
            time.sleep(5)
        self.assertIn('kill: usage', self.kill_dss, '进程存在')

        text = '-----step4:再次查看dss进程,观察CMS服务是否会自动拉起恢复dss,查看集群状态; ' \
               'expect:dss进程不存在,dss未被拉起恢复,集群状态异常-----'
        self.log.info(text)

        time.sleep(30)
        pri_dss_pid2 = self.com.get_pid(self.usernode, 'dssserver')
        self.log.info(pri_dss_pid2)
        self.assertEqual('', pri_dss_pid2, '主节点dss进程存在')

        sta1 = Primary_SH.exec_cm_ctl('query', '-Cv')
        self.log.info(sta1)
        self.assertIn('Manually stopped', sta1.splitlines()[-1].split('|')[0], '集群状态正常')

    def tearDown(self):
        text = '-----step5:恢复环境为初始集群状态; expect:成功-----'
        self.log.info(text)

        self.log.info('-----拉起被停止节点-----')
        start = Primary_SH.exec_cm_ctl('start')
        self.log.info(start)

        self.log.info('---恢复参数默认值---')
        set_param3 = Primary_SH.execute_gsguc('set',
                                              self.constant.GSGUC_SUCCESS_MSG,
                                              f'{self.remote_excute} = {self.remote_excute_default}')
        self.log.info(set_param3)

        set_param4 = Primary_SH.execute_gsguc('set',
                                              self.constant.GSGUC_SUCCESS_MSG,
                                              f'{self.bcast_snapshot} = {self.bcast_snapshot_default}')
        self.log.info(set_param4)

        self.log.info('---重启集群---')
        stop = Primary_SH.exec_cm_ctl('stop')
        self.log.info(stop)
        start = Primary_SH.exec_cm_ctl('start')
        self.log.info(start)

        self.log.info('---查看集群状态---')
        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        p_status = status.splitlines()[-1].split('|')[0].split('6001')[-1]
        if 'Primary' in p_status:
            self.log.info('---集群状态正常，无需恢复为初始状态---')
        else:
            recovery = Primary_SH.exec_cm_ctl(mode='switchover', param='-a')
            self.log.info(recovery)

            self.assertIn(self.constant.cm_switchover_success_msg, recovery,
                          '执行失败' + text)

        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)

        self.assertIn('cluster_state   : Normal', status, '执行失败' + text)
        self.assertIn('P Primary Normal',
                      status.splitlines()[-1].split('|')[0].split('6001')[-1],
                      '执行失败' + text)
        self.assertIn('S Standby Normal',
                      status.splitlines()[-1].split('|')[1].split('6002')[-1],
                      '执行失败' + text)
        self.log.info(f'-----{os.path.basename(__file__)} end-----')
